<template>
  <el-form v-show="visible" label-width="100px">
    <!--SPU名称-->
    <el-form-item label="SPU名称">
      <el-input type="text" placeholder="请输入SPU名称" v-model="spuInfo.spuName"></el-input>
    </el-form-item>
    <!--SPU品牌-->
    <el-form-item label="SPU品牌">
      <el-select placeholder="请选择品牌" v-model="spuInfo.tmId">
        <el-option :label="tm.tmName" :value="tm.id" v-for="(tm,index) in trademarkList" :key="tm.id"></el-option>
      </el-select>
    </el-form-item>
    <!--SPU描述-->
    <el-form-item label="SPU描述">
      <el-input type="textarea" rows="4" placeholder="请输入SPU描述信息" v-model="spuInfo.description"></el-input>
    </el-form-item>
    <!--SPU图片-->
    <el-form-item label="SPU图片">
      <el-upload action="/dev-api/admin/product/fileUpload" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :file-list="spuImageList" multiple>
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
    </el-form-item>
    <!--销售属性-->
    <el-form-item label="销售属性">
      <el-select v-model="attrIdAttrName" :placeholder="`${unSelectedSaleAttrList.length>0?`还有${unSelectedSaleAttrList.length}个未选择`:'没有了'}`">
        <el-option :label="attr.name" :value="attr.id+':'+attr.name" v-for="(attr,index) in unSelectedSaleAttrList" :key="attr.id"></el-option>
      </el-select>
      <el-button type="primary" icon="el-icon-plus" @click="addAttr" :disabled="!attrIdAttrName">添加销售属性</el-button>
    </el-form-item>
    <!--表格-->
    <el-form-item>
      <!--表格-->
      <el-table :data="spuInfo.spuSaleAttrList" border stripe style="width: 100%">
        <el-table-column type="index" label="序号" width="80" align="center">
        </el-table-column>
        <el-table-column label="属性名" width="150" prop="saleAttrName"></el-table-column>

        <el-table-column label="属性值名称列表" prop="spuSaleAttrValueList">

          <template slot-scope="{row,$index}">
            <el-tag :key="attr.id" v-for="(attr,index) in row.spuSaleAttrValueList" closable :disable-transitions="false" @close="handleClose(row.spuSaleAttrValueList,index)">
              {{attr.saleAttrValueName}}
            </el-tag>
            <!--attr.edit这个属性为true,表示的是文本框已经展示出来了,是编辑模式,否则就是查看模式-->
            <el-input class="input-new-tag" v-if="row.edit" v-model="row.saleAttrValueName" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)">
            </el-input>
            <el-button v-else class="button-new-tag" size="small" @click="showInput(row)">+ 添加</el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template slot-scope="{row,$index}">
            <el-popconfirm :title="`您确定要删除  吗`" @onConfirm="deleteVal($index)">
              <HintButton size="mini" type="danger" icon="el-icon-delete" title="删除属性值" slot="reference"></HintButton>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
    </el-form-item>
    <!--两个按钮-->
    <el-form-item>
      <el-button type="primary" @click="save">保存</el-button>
      <el-button @click="back">取消</el-button>
    </el-form-item>
  </el-form>
</template>
<script>
export default {
  name: 'SpuForm',
  props: ['visible'],
  data() {
    return {
      // spuId: '', // spuId的数据,是修改spuInfo对象的时候传递进来的
      spuInfo: {
        spuName: '', // spuInfo对象的名字
        description: '', // spuInfo对象的描述信息
        category3Id: '', // 三级分类的id值
        tmId: '', // 品牌的id
        spuSaleAttrList: [], // spuInfo对象中的销售属性数组数据
        spuImageList: [] // 图片列表数据
      },

      trademarkList: [], // 所有的品牌列表数据
      saleAttrList: [], // 所有的销售属性数据
      spuImageList: [], // 所有的图片列表数据
      attrIdAttrName: '', // 用来存储选中的销售属性的id和名字的
      // 上传图片所需的两个表达式
      dialogImageUrl: '',
      dialogVisible: false
    }
  },
  // 计算属性
  computed: {
    unSelectedSaleAttrList() {
      // 解构出所有的销售属性数组和spuInfo对象中的销售属性数组
      const {
        saleAttrList,
        spuInfo: { spuSaleAttrList }
      } = this
      // 进行数据过滤,留下的数组会返回到unSelectedSaleAttrList数组中(没有选中的数据)
      return saleAttrList.filter(
        (sa) => !spuSaleAttrList.some((ssa) => ssa.saleAttrName === sa.name)
      )
    }
  },
  methods: {
    // 取消
    back() {
      this.$emit('update:visible', false)
    },
    // 修改spuInfo对象的初始化的相关方法
    initUpdateData(spuId) {
      // spuId数据如果改变,页面是不需要进行重新绘制的,所以,该数据可以不是响应式的数据,就没有必要存储到data中,直接挂在this上即可
      this.spuId = spuId
      // 1. 根据spuId获取对应的spuInfo对象数据
      this.getSpuInfo()
      // 2. 获取所有的品牌信息数据
      this.getTrademarkList()
      // 3. 获取所有的销售属性数据
      this.getSaleAttrList()
      // 4. 获取当前的spuInfo对象中所有的图片信息数据
      this.getSpuImageList()
    },
    // 1. 根据spuId获取对应的spuInfo对象数据
    async getSpuInfo() {
      const result = await this.$API.spu.getSpuInfoById(this.spuId)
      // 需要判断成功与否,简写
      this.spuInfo = result.data
    },
    // 2. 获取所有的品牌信息数据
    async getTrademarkList() {
      const result = await this.$API.trademark.getTrademarkList()
      this.trademarkList = result.data
    },
    // 3. 获取所有的销售属性数据
    async getSaleAttrList() {
      const result = await this.$API.spu.getBaseSaleAttrList()
      this.saleAttrList = result.data
    },
    // 4. 获取当前的spuInfo对象中所有的图片信息数据
    async getSpuImageList() {
      const result = await this.$API.sku.getSpuImageList(this.spuId)
      // 更新数据
      const spuImageList = result.data
      spuImageList.forEach((item) => {
        item.name = item.imgName
        item.url = item.imgUrl
      })
      this.spuImageList = spuImageList
    },

    // 上传图片所需要的回调函数
    // 删掉图片的回调函数
    handleRemove(file, fileList) {
      // fileList是一个数组,移除图片后的数组
      this.spuImageList = fileList
    },
    // 预览图片的相关的方法
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url // 设置预览图片的地址
      this.dialogVisible = true // 是否开启预览的效果
    },
    // 图片上传成功的回调函数
    handleAvatarSuccess(res, file, fileList) {
      this.spuImageList = fileList
    },
    // 上传图片之前的回调
    beforeAvatarUpload(file) {
      // 限定上传图片的格式的
      const isJPG = ['image/jpeg', 'image/png'].includes(file.type)
      // 限制图片的大小
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG/PNG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!')
      }
      return isJPG && isLt2M
    },

    // 删除某个销售属性的数据
    deleteVal(index) {
      this.spuInfo.spuSaleAttrList.splice(index,1)
    },
    // 操作销售属性值的相关方法
    handleClose(valueList, index) {
      valueList.splice(index, 1)
    },
    // 查看模式,文本框输入内容后,要进行属性值添加的操作了
    handleInputConfirm(attr) {
      const saleAttrValueName = attr.saleAttrValueName
      // 如果当前的文本框中没有任何的数据,那么直接设置为查看模式,添加了优化空格的代码
      if (!saleAttrValueName || !saleAttrValueName.trim()) {
        attr.edit = false
        return
      }
      // 此时文本框中是有数据的
      const isRepeat = attr.spuSaleAttrValueList.some(
        (item) => item.saleAttrValueName === saleAttrValueName.trim()
      )
      // 没有重复的情况下,添加数据
      if (!isRepeat) {
        attr.spuSaleAttrValueList.push({
          baseSaleAttrId: attr.baseSaleAttrId,
          saleAttrValueName
        })
      } else {
        this.$message.warning('您输入了重复的数据,请重新的输入')
      }
      attr.edit = false
      attr.saleAttrValueName = ''
    },
    // 编辑模式的回调
    showInput(attr) {
      // 先判断当前的对象中是否存在edit标识属性
      if (!attr.hasOwnProperty('edit')) {
        this.$set(attr, 'edit', true)
      } else {
        attr.edit = true
      }
      this.$nextTick(() => {
        // 获取焦点,个别同学的代码会报错
        this.$refs.saveTagInput.focus()
      })
    },
    // 点击按钮,添加销售属性
    addAttr() {
      // 获取选中的销售属性数据中的id和名字
      const [baseSaleAttrId, saleAttrName] = this.attrIdAttrName.split(':')
      // 向销售属性数组中添加数据
      this.spuInfo.spuSaleAttrList.push({
        baseSaleAttrId,
        saleAttrName,
        spuSaleAttrValueList: []
      })
      // 清空数据的操作
      this.attrIdAttrName = ''
    },
    // 保存操作
    async save() {
      const { spuInfo, spuImageList } = this
      // 图片过滤后的数据怼到spuInfo对象的spuImageList数组中
      spuInfo.spuImageList = spuImageList.map((item) => ({
        imgName: item.name,
        // 如果有上传的图片,图片的真正的地址不在url中,而是在response.data中
        imgUrl: item.response ? item.response.data : item.imgUrl
      }))
      // 针对于销售属性的数据进行过滤的操作
      spuInfo.spuSaleAttrList = spuInfo.spuSaleAttrList.filter((item) => {
        // 如果新添加的销售属性中的存储属性值的数组的长度大于0,最少添加了一个属性值,就需要过滤数据了
        if (item.spuSaleAttrValueList.length > 0) {
          delete item.edit
          delete item.saleAttrValueName
          return true
        }
        return false
      })
      // 调用接口,发送请求
      try {
        await this.$API.spu.addOrUpdateSpuInfo(spuInfo)
        // 提示信息
        this.$message.success('操作成功')
        // 关闭对话框
        this.back()
        // 重置数据
        this.resetData()
        // 通知父级组件操作已经成功
        this.$emit('saveSuccess')
      } catch (error) {
        // 报错/操作失败
        this.$message.error(error.message || '操作失败')
      }
      // 接口传入的数据(spuInfo)
      // 如果失败,则提示错误信息
      // 如果成功,有提示信息,关闭当前的窗口,主界面还要更新,重置数据
    },
    // 重置数据
    resetData() {
      this.spuInfo = {
        spuName: '', // spuInfo对象的名字
        description: '', // spuInfo对象的描述信息
        category3Id: '', // 三级分类的id值
        tmId: '', // 品牌的id
        spuSaleAttrList: [], // spuInfo对象中的销售属性数组数据
        spuImageList: [] // 图片列表数据
      }
      this.trademarkList = [] // 所有的品牌列表数据
      this.saleAttrList = [] // 所有的销售属性数据
      this.spuImageList = [] // 所有的图片列表数据
      this.attrIdAttrName = '' // 用来存储选中的销售属性的id和名字的
      // 上传图片所需的两个表达式
      this.dialogImageUrl = ''
      this.dialogVisible = false
    },
    // 添加spuInfo对象所需要的初始化的数据
    initAddData(category3Id){
      this.spuInfo.category3Id = category3Id
      // 获取所有的品牌信息数据
      this.getTrademarkList()
      // 获取所有的销售属性数据
      this.getSaleAttrList()
    }
  }
}
</script>
<style>
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>



